package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.bookingDto;
import com.zzyl.entity.booking;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.ReservationStatus;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.bookingMapper;
import com.zzyl.service.bookingService;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.BookingVo;
import com.zzyl.vo.bookingCountVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;

@Service
public class bookingServiceImpl implements bookingService {
    @Autowired
    private bookingMapper bookingMapper;

    @Override
    public Integer getCountData() {
        Long userId = UserThreadLocal.getUserId();//从线程当中获取当前用户id
        return bookingMapper.getCountData(userId);//将查询到的当前用户当天的取消预约数量返回
    }

    @Override
    public void addbooking(bookingDto bookingdto) {
        Long userId = UserThreadLocal.getUserId();//从ThreadLocal中获取存储的用户id
        Integer count = bookingMapper.getUserdil(userId);//调用对应方法去数据库查询该用户当天的取消次数
        if (count >= 3) {//如果大于3抛出异常响应对应状态码
            throw new BaseException(BasicEnum.RESERVATION_CANCEL_COUNT_UPPER_LIMIT);
        }//如果不大于3则进行新增操作
        booking booking = BeanUtil.toBean(bookingdto, booking.class);//转换成实体类型
        booking.setStatus(ReservationStatus.PENDING.getOrdinal());//设置为待报道的状态因为是新增
        booking.setCreateBy(userId);//将获取到的用户id赋值给实体类进行插入操作
        bookingMapper.insertBooking(booking);//调用方法进行新增
    }

    @Override
    public PageResponse<BookingVo> getPage(Integer pageNum, Integer pageSize, Integer status) {
        PageHelper.startPage(pageNum, pageSize);//利用插件设置分页条件
        Long userId = UserThreadLocal.getUserId();//从ThreadLocal中获取当前用户的userId
        Page<BookingVo> bookingVos =  bookingMapper.getPage(status,userId);//调用mapper的分页查询方法
        return PageResponse.of(bookingVos,BookingVo.class);//将mapper返回的结果转换
    }

    @Override
    public void deletebooking(Long id) {
        bookingMapper.deleteBooking(id);
    }

    @Override
    public List<bookingCountVo> getCount(List<String> times) {
        return bookingMapper.getCount(times);
    }

    @Override
    public void updateBooking(Long id) {
        Long userId = UserThreadLocal.getUserId();
        //1.先根据id查询一下是否有这个预约信息 //如果有修改它的状态为取消
        booking booking = bookingMapper.findByid(id);
        //2.判断根据前端传递过来的id查找到的数据是否为空 //不为空则证明有这个预约信息 修改他的状态为取消
        if (ObjectUtil.isNotEmpty(booking)) {
            booking.setCreateBy(userId);
            booking.setStatus(ReservationStatus.CANCELED.getOrdinal());//设置状态为取消
            bookingMapper.updateBooking(booking);//调用mapper层修改方法
        }
    }

    @Override
    public List<bookingCountVo> getCountVo(LocalDateTime startTime) {
        LocalDateTime endTime = startTime.plusDays(1);//将Controller层传递过来的时间对象当作开始时间
        System.out.println(endTime);//从它的基础上加1作为结束时间
        return bookingMapper.getCountVo(startTime,endTime);//调用mapper方法返回集合
    }

    @Override
    public void updateStatus() {
        List<booking> expiredBookings = new ArrayList<>();//存储要修改为过期状态的预约信息
        //1.获取当天日期时间
        LocalDate today = LocalDate.now();
        //2.获取当天日期的起始时间
        LocalDateTime startOfDay = today.atStartOfDay(ZoneId.systemDefault()).toLocalDateTime();
        //3.获取当天时间的结束时间
        LocalDateTime endOfDay = startOfDay.plusDays(1);
        //4.将当天时间内的所有预约信息获取出来 调用方法参数为 起始时间 结束时间
        List<booking> bookings =  bookingMapper.getTodayBooking(startOfDay,endOfDay);
        //循环遍历判断修改预约信息状态
        bookings.forEach(v ->{//判断预约信息的预约时间是否在当前时间之前且状态为待报道 如果是修改成过期状态
            if(v.getTime().isBefore(LocalDateTime.now()) && v.getStatus() == ReservationStatus.PENDING.getOrdinal()){
                v.setStatus(ReservationStatus.EXPIRED.getOrdinal());
                expiredBookings.add(v);
            }
        });
        bookingMapper.updateStatus(expiredBookings);

    }
}
